home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / russell / gc.lha / misc.c < prev    next >
C/C++ Source or Header  |  1993-04-26  |  19KB  |  691 lines

  1. /* 
  2.  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3.  * Copyright (c) 1991,1992 by Xerox Corporation.  All rights reserved.
  4.  *
  5.  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  6.  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  7.  *
  8.  * Permission is hereby granted to copy this garbage collector for any purpose,
  9.  * provided the above notices are retained on all copies.
  10.  */
  11.  
  12. #define DEBUG       /* Some run-time consistency checks */
  13. #undef DEBUG
  14. #define VERBOSE
  15. #undef VERBOSE
  16.  
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #define I_HIDE_POINTERS    /* To make GC_call_with_alloc_lock visible */
  20. #include "gc_private.h"
  21.  
  22. # ifdef THREADS
  23. #   ifdef PCR
  24. #     include "pcr/il/PCR_IL.h"
  25.       struct PCR_Th_MLRep GC_allocate_ml;
  26. #   else
  27.     --> declare allocator lock here
  28. #   endif
  29. # endif
  30.  
  31. struct _GC_arrays GC_arrays = { 0 };
  32.  
  33. /* Initialize GC_obj_kinds properly and standard free lists properly.      */
  34. /* This must be done statically since they may be accessed before     */
  35. /* GC_init is called.                            */
  36. struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
  37. /* PTRFREE */ { &GC_aobjfreelist[0], &GC_areclaim_list[0],
  38.         GC_no_mark_proc, FALSE },
  39. /* NORMAL  */ { &GC_objfreelist[0], &GC_reclaim_list[0],
  40.         GC_normal_mark_proc, TRUE },
  41. };
  42.  
  43. ptr_t GC_stackbottom = 0;
  44.  
  45. word GC_hincr;
  46.  
  47. int GC_n_kinds = 2;
  48.  
  49. bool GC_dont_gc = 0;
  50.  
  51. extern signed_word GC_mem_found;
  52.  
  53. # ifdef ALL_INTERIOR_POINTERS
  54. #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1))
  55. # else
  56. #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
  57. # endif
  58.  
  59. # ifdef MERGE_SIZES
  60.     /* Set things up so that GC_size_map[i] >= words(i),        */
  61.     /* but not too much bigger                        */
  62.     /* and so that size_map contains relatively few distinct entries     */
  63.     /* This is stolen from Russ Atkinson's Cedar quantization        */
  64.     /* alogrithm (but we precompute it).                */
  65.     
  66. #   if (CPP_WORDSZ != 32) 
  67.       --> fix the following code
  68. #   endif
  69.  
  70.  
  71.  
  72.     void GC_init_size_map()
  73.     {
  74.     register unsigned i;
  75.     register unsigned sz_rounded_up = 0;
  76.  
  77.     /* Map size 0 to 1.  This avoids problems at lower levels. */
  78.       GC_size_map[0] = 1;
  79.     /* One word objects don't have to be 2 word aligned.       */
  80.       GC_size_map[1] = 1;
  81.       GC_size_map[2] = 1;
  82.       GC_size_map[3] = 1;
  83.       GC_size_map[4] = ROUNDED_UP_WORDS(4);
  84.     for (i = 5; i <= 32; i++) {
  85. #           ifdef ALIGN_DOUBLE
  86.           GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
  87. #           else
  88.           GC_size_map[i] = ROUNDED_UP_WORDS(i);
  89. #           endif
  90.     }
  91.     
  92.     for (i = 33; i <= WORDS_TO_BYTES(MAXOBJSZ); i++) {
  93.         if (sz_rounded_up < ROUNDED_UP_WORDS(i)) {
  94.             register int size = ROUNDED_UP_WORDS(i);
  95.                 register unsigned m = 0;
  96.             
  97.                 while (size > 7) {
  98.                   m += 1;
  99.                   size += 1;
  100.                   size >>= 1;
  101.                 }
  102.             sz_rounded_up = size << m;
  103.         if (sz_rounded_up > MAXOBJSZ) {
  104.             sz_rounded_up = MAXOBJSZ;
  105.         }
  106.         }
  107.         GC_size_map[i] = sz_rounded_up;
  108.     }
  109.     }
  110. # endif
  111.  
  112. # ifdef ALL_INTERIOR_POINTERS
  113. #   define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ))
  114. #   define ADD_SLOP(bytes) ((bytes)+1)
  115. # else
  116. #   define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
  117. #   define ADD_SLOP(bytes) (bytes)
  118. # endif
  119.  
  120. /*
  121.  * The following is a gross hack to deal with a problem that can occur
  122.  * on machines that are sloppy about stack frame sizes, notably SPARC.
  123.  * Bogus pointers may be written to the stack and not cleared for
  124.  * a LONG time, because they always fall into holes in stack frames
  125.  * that are not written.  We partially address this by randomly clearing
  126.  * sections of the stack whenever we get control.
  127.  */
  128. word GC_stack_last_cleared = 0;    /* GC_no when we last did this */
  129. # define CLEAR_SIZE 213
  130. # define CLEAR_THRESHOLD 10000
  131. # define DEGRADE_RATE 50
  132.  
  133. ptr_t GC_min_sp;    /* Coolest stack pointer value from which we've */
  134.             /* already cleared the stack.            */
  135.             
  136. # ifdef STACK_GROWS_DOWN
  137. #   define COOLER_THAN >
  138. #   define HOTTER_THAN <
  139. #   define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \
  140.                 else {(x) = (ptr_t)ONES;}
  141. #   define MAKE_HOTTER(x,y) (x) -= (y)
  142. # else
  143. #   define COOLER_THAN <
  144. #   define HOTTER_THAN >
  145. #   define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;}
  146. #   define MAKE_HOTTER(x,y) (x) += (y)
  147. # endif
  148.  
  149. ptr_t GC_high_water;
  150.             /* "hottest" stack pointer value we have seen    */
  151.             /* recently.  Degrades over time.        */
  152. /*ARGSUSED*/
  153. void GC_clear_stack_inner(d)
  154. word *d;
  155. {
  156.     word dummy[CLEAR_SIZE];
  157.     
  158.     bzero((char *)dummy, (int)(CLEAR_SIZE*sizeof(word)));
  159. #   ifdef THREADS
  160.       GC_noop(dummy);
  161. #   else
  162.         if ((ptr_t)(dummy) COOLER_THAN GC_min_sp) {
  163.             GC_clear_stack_inner(dummy);
  164.         }
  165. #   endif
  166. }
  167.  
  168. void GC_clear_stack()
  169. {
  170.     word dummy;
  171.  
  172.  
  173. # ifdef THREADS
  174.     GC_clear_stack_inner(&dummy);
  175. # else
  176.     if (GC_gc_no > GC_stack_last_cleared) {
  177.         /* Start things over, so we clear the entire stack again */
  178.         if (GC_stack_last_cleared == 0) GC_high_water = GC_stackbottom;
  179.         GC_min_sp = GC_high_water;
  180.         GC_stack_last_cleared = GC_gc_no;
  181.     }
  182.     /* Adjust GC_high_water */
  183.         MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE));
  184.         if ((word)(&dummy) HOTTER_THAN (word)GC_high_water) {
  185.             GC_high_water = (ptr_t)(&dummy);
  186.         }
  187.     if ((word)(&dummy) COOLER_THAN (word)GC_min_sp) {
  188.         GC_clear_stack_inner(&dummy);
  189.         GC_min_sp = (ptr_t)(&dummy);
  190.     }
  191. # endif
  192. }
  193.  
  194. /* allocate lb bytes for an object of kind k */
  195. ptr_t GC_generic_malloc(lb, k)
  196. register word lb;
  197. register int k;
  198. {
  199. register word lw;
  200. register ptr_t op;
  201. register ptr_t *opp;
  202. DCL_LOCK_STATE;
  203.  
  204.     DISABLE_SIGNALS();
  205.     LOCK();
  206.     if( SMALL_OBJ(lb) ) {
  207. #       ifdef MERGE_SIZES
  208.       lw = GC_size_map[lb];
  209. #    else
  210.       lw = ROUNDED_UP_WORDS(lb);
  211.       if (lw == 0) lw = 1;
  212. #       endif
  213.     opp = &(GC_obj_kinds[k].ok_freelist[lw]);
  214.         if( (op = *opp) == 0 ) {
  215.             if (!GC_is_initialized) {
  216.                 GC_init_inner();
  217.                 ENABLE_SIGNALS();
  218.                 /* This may have fixed GC_size_map */
  219.                 UNLOCK();
  220.                 return(GC_generic_malloc(lb, k));
  221.             }
  222.             GC_clear_stack();
  223.         op = GC_allocobj(lw, k);
  224.         if (op == 0) goto out;
  225.         }
  226.         /* Here everything is in a consistent state.    */
  227.         /* We assume the following assignment is    */
  228.         /* atomic.  If we get aborted            */
  229.         /* after the assignment, we lose an object,    */
  230.         /* but that's benign.                */
  231.         /* Volatile declarations may need to be added    */
  232.         /* to prevent the compiler from breaking things.*/
  233.         *opp = obj_link(op);
  234.         obj_link(op) = 0;
  235.     } else {
  236.     register struct hblk * h;
  237.     
  238.     if (!GC_is_initialized) GC_init_inner();
  239.     lw = ROUNDED_UP_WORDS(lb);
  240.     while ((h = GC_allochblk(lw, k)) == 0) {
  241.        GC_collect_or_expand(divHBLKSZ(lb) + 1);
  242.     }
  243.     if (h == 0) {
  244.         op = 0;
  245.     } else {
  246.         op = (ptr_t) (h -> hb_body);
  247.     }
  248.     }
  249.     GC_words_allocd += lw;
  250.     
  251. out:
  252.     UNLOCK();
  253.     ENABLE_SIGNALS();
  254.     return((ptr_t)op);
  255. }
  256.  
  257. /* Analogous to the above, but assumes a small object size, and     */
  258. /* bypasses MERGE_SIZES mechanism.  Used by gc_inline.h.        */
  259. ptr_t GC_generic_malloc_words_small(lw, k)
  260. register word lw;
  261. register int k;
  262. {
  263. register ptr_t op;
  264. register ptr_t *opp;
  265. DCL_LOCK_STATE;
  266.  
  267.     LOCK();
  268.     DISABLE_SIGNALS();
  269.     opp = &(GC_obj_kinds[k].ok_freelist[lw]);
  270.     if( (op = *opp) == 0 ) {
  271.         if (!GC_is_initialized) {
  272.             GC_init_inner();
  273.         }
  274.         GC_clear_stack();
  275.     op = GC_allocobj(lw, k);
  276.     if (op == 0) goto out;
  277.     }
  278.     *opp = obj_link(op);
  279.     obj_link(op) = 0;
  280.     GC_words_allocd += lw;
  281.     
  282. out:
  283.     UNLOCK();
  284.     ENABLE_SIGNALS();
  285.     return((ptr_t)op);
  286. }
  287.  
  288. /* Allocate lb bytes of atomic (pointerfree) data */
  289. # ifdef __STDC__
  290.     extern_ptr_t GC_malloc_atomic(size_t lb)
  291. # else
  292.     extern_ptr_t GC_malloc_atomic(lb)
  293.     size_t lb;
  294. # endif
  295. {
  296. register ptr_t op;
  297. register ptr_t * opp;
  298. register word lw;
  299. DCL_LOCK_STATE;
  300.  
  301.     if( SMALL_OBJ(lb) ) {
  302. #       ifdef MERGE_SIZES
  303.       lw = GC_size_map[lb];
  304. #    else
  305.       lw = ROUNDED_UP_WORDS(lb);
  306. #       endif
  307.     opp = &(GC_aobjfreelist[lw]);
  308.     FASTLOCK();
  309.         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
  310.             FASTUNLOCK();
  311.             return(GC_generic_malloc((word)lb, PTRFREE));
  312.         }
  313.         /* See above comment on signals.    */
  314.         *opp = obj_link(op);
  315.         GC_words_allocd += lw;
  316.         FASTUNLOCK();
  317.         return((extern_ptr_t) op);
  318.    } else {
  319.        return((extern_ptr_t)
  320.                GC_generic_malloc((word)lb, PTRFREE));
  321.    }
  322. }
  323.  
  324. /* Allocate lb bytes of composite (pointerful) data */
  325. # ifdef __STDC__
  326.     extern_ptr_t GC_malloc(size_t lb)
  327. # else
  328.     extern_ptr_t GC_malloc(lb)
  329.     size_t lb;
  330. # endif
  331. {
  332. register ptr_t op;
  333. register ptr_t *opp;
  334. register word lw;
  335. DCL_LOCK_STATE;
  336.  
  337.     if( SMALL_OBJ(lb) ) {
  338. #       ifdef MERGE_SIZES
  339.       lw = GC_size_map[lb];
  340. #    else
  341.       lw = ROUNDED_UP_WORDS(lb);
  342. #       endif
  343.     opp = &(GC_objfreelist[lw]);
  344.     FASTLOCK();
  345.         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
  346.             FASTUNLOCK();
  347.             return(GC_generic_malloc((word)lb, NORMAL));
  348.         }
  349.         /* See above comment on signals.    */
  350.         *opp = obj_link(op);
  351.         obj_link(op) = 0;
  352.         GC_words_allocd += lw;
  353.         FASTUNLOCK();
  354.         return((extern_ptr_t) op);
  355.    } else {
  356.        return((extern_ptr_t)
  357.               GC_generic_malloc((word)lb, NORMAL));
  358.    }
  359. }
  360.  
  361. /* Change the size of the block pointed to by p to contain at least   */
  362. /* lb bytes.  The object may be (and quite likely will be) moved.     */
  363. /* The kind (e.g. atomic) is the same as that of the old.          */
  364. /* Shrinking of large blocks is not implemented well.                 */
  365. # ifdef __STDC__
  366.     extern_ptr_t GC_realloc(extern_ptr_t p, size_t lb)
  367. # else
  368.     extern_ptr_t GC_realloc(p,lb)
  369.     extern_ptr_t p;
  370.     size_t lb;
  371. # endif
  372. {
  373. register struct hblk * h;
  374. register hdr * hhdr;
  375. register signed_word sz;     /* Current size in bytes    */
  376. register word orig_sz;     /* Original sz in bytes    */
  377. int obj_kind;
  378.  
  379.     if (p == 0) return(GC_malloc(lb));    /* Required by ANSI */
  380.     h = HBLKPTR(p);
  381.     hhdr = HDR(h);
  382.     sz = hhdr -> hb_sz;
  383.     obj_kind = hhdr -> hb_obj_kind;
  384.     sz = WORDS_TO_BYTES(sz);
  385.     orig_sz = sz;
  386.  
  387.     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
  388.     /* Round it up to the next whole heap block */
  389.       
  390.       sz = (sz+HDR_BYTES+HBLKSIZE-1)
  391.         & (~HBLKMASK);
  392.       sz -= HDR_BYTES;
  393.       hhdr -> hb_sz = BYTES_TO_WORDS(sz);
  394.       /* Extra area is already cleared by allochblk. */
  395.     }
  396.     if (ADD_SLOP(lb) <= sz) {
  397.     if (lb >= (sz >> 1)) {
  398.         if (orig_sz > lb) {
  399.           /* Clear unneeded part of object to avoid bogus pointer */
  400.           /* tracing.                          */
  401.             bzero(((char *)p) + lb, (int)(orig_sz - lb));
  402.         }
  403.         return(p);
  404.     } else {
  405.         /* shrink */
  406.           extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind);
  407.  
  408.           if (result == 0) return(0);
  409.               /* Could also return original object.  But this     */
  410.               /* gives the client warning of imminent disaster.    */
  411.           bcopy(p, result, (int)lb);
  412.           GC_free(p);
  413.           return(result);
  414.     }
  415.     } else {
  416.     /* grow */
  417.       extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind);
  418.  
  419.       if (result == 0) return(0);
  420.       bcopy(p, result, (int)sz);
  421.       GC_free(p);
  422.       return(result);
  423.     }
  424. }
  425.  
  426. /* Return a pointer to the base address of p, given a pointer to a    */
  427. /* an address within an object.  Return 0 o.w.                */
  428. # ifdef __STDC__
  429.     extern_ptr_t GC_base(extern_ptr_t p)
  430. # else
  431.     extern_ptr_t GC_base(p)
  432.     extern_ptr_t p;
  433. # endif
  434. {
  435.     register word r;
  436.     register struct hblk *h;
  437.     register hdr *candidate_hdr;
  438.     
  439.     r = (word)p;
  440.     h = HBLKPTR(r);
  441.     candidate_hdr = HDR(r);
  442.     if (candidate_hdr == 0) return(0);
  443.     /* If it's a pointer to the middle of a large object, move it    */
  444.     /* to the beginning.                        */
  445.     while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
  446.        h = h - (int)candidate_hdr;
  447.        r = (word)h + HDR_BYTES;
  448.        candidate_hdr = HDR(h);
  449.     }
  450.     if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
  451.     /* Make sure r points to the beginning of the object */
  452.     r &= ~(WORDS_TO_BYTES(1) - 1);
  453.         {
  454.         register int offset =
  455.                 (word *)r - (word *)(HBLKPTR(r)) - HDR_WORDS;
  456.         register signed_word sz = candidate_hdr -> hb_sz;
  457.         register int correction;
  458.             
  459.         correction = offset % sz;
  460.         r -= (WORDS_TO_BYTES(correction));
  461.         if (((word *)r + sz) > (word *)(h + 1)
  462.             && sz <= MAXOBJSZ) {
  463.             return(0);
  464.         }
  465.     }
  466.     return((extern_ptr_t)r);
  467. }
  468.  
  469. /* Return the size of an object, given a pointer to its base.        */
  470. /* (For small obects this also happens to work from interior pointers,    */
  471. /* but that shouldn't be relied upon.)                    */
  472. # ifdef __STDC__
  473.     size_t GC_size(extern_ptr_t p)
  474. # else
  475.     size_t GC_size(p)
  476.     extern_ptr_t p;
  477. # endif
  478. {
  479.     register int sz;
  480.     register hdr * hhdr = HDR(p);
  481.     
  482.     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
  483.     if (sz < 0) {
  484.         return(-sz);
  485.     } else {
  486.         return(sz);
  487.     }
  488. }
  489.  
  490. /* Explicitly deallocate an object p.                */
  491. # ifdef __STDC__
  492.     void GC_free(extern_ptr_t p)
  493. # else
  494.     void GC_free(p)
  495.     extern_ptr_t p;
  496. # endif
  497. {
  498.     register struct hblk *h;
  499.     register hdr *hhdr;
  500.     register signed_word sz;
  501.     register ptr_t * flh;
  502.     register struct obj_kind * ok;
  503.  
  504.     if (p == 0) return;
  505.         /* Required by ANSI.  It's not my fault ...    */
  506.     h = HBLKPTR(p);
  507.     hhdr = HDR(h);
  508.     sz = hhdr -> hb_sz;
  509.     GC_mem_freed += sz;
  510.     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
  511.   
  512.     if (sz > MAXOBJSZ) {
  513.     GC_freehblk(h);
  514.     } else {
  515.         ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
  516.     if (ok -> ok_init) {
  517.         bzero((char *)((word *)p + 1), (int)(WORDS_TO_BYTES(sz-1)));
  518.     }
  519.     flh = &(ok -> ok_freelist[sz]);
  520.     obj_link(p) = *flh;
  521.     *flh = (ptr_t)p;
  522.     }
  523. }
  524.  
  525. bool GC_is_initialized = FALSE;
  526.  
  527. void GC_init()
  528. {
  529.     DCL_LOCK_STATE;
  530.     
  531.     DISABLE_SIGNALS();
  532.     LOCK();
  533.     GC_init_inner();
  534.     UNLOCK();
  535.     ENABLE_SIGNALS();
  536.  
  537. }
  538.  
  539. void GC_init_inner()
  540. {
  541.     word dummy;
  542.     
  543.     if (GC_is_initialized) return;
  544.     GC_is_initialized = TRUE;
  545. #   ifndef THREADS
  546.       if (GC_stackbottom == 0) {
  547.     GC_stackbottom = GC_get_stack_base();
  548.       }
  549. #   endif
  550.     if  (sizeof (ptr_t) != sizeof(word)) {
  551.         GC_err_printf0("sizeof (ptr_t) != sizeof(word)\n");
  552.         ABORT("sizeof (ptr_t) != sizeof(word)\n");
  553.     }
  554.     if  (sizeof (signed_word) != sizeof(word)) {
  555.         GC_err_printf0("sizeof (signed_word) != sizeof(word)\n");
  556.         ABORT("sizeof (signed_word) != sizeof(word)\n");
  557.     }
  558.     if  (sizeof (struct hblk) != HBLKSIZE) {
  559.         GC_err_printf0("sizeof (struct hblk) != HBLKSIZE\n");
  560.         ABORT("sizeof (struct hblk) != HBLKSIZE\n");
  561.     }
  562. #   ifndef THREADS
  563. #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
  564.       GC_err_printf0(
  565.         "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
  566.       ABORT("stack direction 1\n");
  567. #     endif
  568. #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
  569.       GC_err_printf0(
  570.         "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
  571.       ABORT("stack direction 2\n");
  572. #     endif
  573. #     ifdef STACK_GROWS_DOWN
  574.         if ((word)(&dummy) > (word)GC_stackbottom) {
  575.           GC_err_printf0(
  576.               "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
  577.           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
  578.                       (unsigned long) (&dummy),
  579.                       (unsigned long) GC_stackbottom);
  580.           ABORT("stack direction 3\n");
  581.         }
  582. #     else
  583.         if ((word)(&dummy) < (word)GC_stackbottom) {
  584.           GC_err_printf0(
  585.               "STACK_GROWS_UP is defd, but stack appears to grow down\n");
  586.           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
  587.                           (unsigned long) (&dummy),
  588.                         (unsigned long) GC_stackbottom);
  589.           ABORT("stack direction 4");
  590.         }
  591. #     endif
  592. #   endif
  593. #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
  594.       if ((word)(-1) < (word)0) {
  595.         GC_err_printf0("The type word should be an unsigned integer type\n");
  596.         GC_err_printf0("It appears to be signed\n");
  597.         ABORT("word");
  598.       }
  599. #   endif
  600.     if ((signed_word)(-1) >= (signed_word)0) {
  601.         GC_err_printf0(
  602.             "The type signed_word should be a signed integer type\n");
  603.         GC_err_printf0("It appears to be unsigned\n");
  604.         ABORT("signed_word");
  605.     }
  606.     
  607.     GC_hincr = HINCR;
  608.     GC_init_headers();
  609.     GC_bl_init();
  610.     GC_mark_init();
  611.     if (!GC_expand_hp_inner(GC_hincr)) {
  612.         GC_printf0("Can't start up: no memory\n");
  613.         EXIT();
  614.     }
  615.     GC_register_displacement_inner(0L);
  616. #   ifdef MERGE_SIZES
  617.       GC_init_size_map();
  618. #   endif
  619.     /* Add initial guess of root sets */
  620.       GC_register_data_segments();
  621. #   ifdef PCR
  622.       PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever);
  623.       PCR_IL_Unlock();
  624.       GC_pcr_install();
  625. #   endif
  626.     /* Get black list set up */
  627.       (void)GC_gcollect_inner(TRUE);
  628.       (void)GC_gcollect_inner(TRUE);
  629.     /* Convince lint that some things are used */
  630.       {
  631.           extern char * GC_copyright[];
  632.           GC_noop(GC_copyright, GC_find_header,
  633.                   GC_tl_mark, GC_call_with_alloc_lock);
  634.       }
  635. }
  636.  
  637. /* A version of printf that is unlikely to call malloc, and is thus safer */
  638. /* to call from the collector in case malloc has been bound to GC_malloc. */
  639. /* Assumes that no more than 1023 characters are written at once.      */
  640. /* Assumes that all arguments have been converted to something of the      */
  641. /* same size as long, and that the format conversions expect something      */
  642. /* of that size.                              */
  643. void GC_printf(format, a, b, c, d, e, f)
  644. char * format;
  645. long a, b, c, d, e, f;
  646. {
  647.     char buf[1025];
  648.     
  649.     buf[1024] = 0x15;
  650.     (void) sprintf(buf, format, a, b, c, d, e, f);
  651.     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
  652. #   ifdef OS2
  653.       /* We hope this doesn't allocate */
  654.       if (fwrite(buf, 1, strlen(buf), stdout) != strlen(buf))
  655.           ABORT("write to stdout failed");
  656. #   else
  657.       if (write(1, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
  658. #   endif
  659. }
  660.  
  661. void GC_err_printf(format, a, b, c, d, e, f)
  662. char * format;
  663. long a, b, c, d, e, f;
  664. {
  665.     char buf[1025];
  666.     
  667.     buf[1024] = 0x15;
  668.     (void) sprintf(buf, format, a, b, c, d, e, f);
  669.     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
  670. #   ifdef OS2
  671.       /* We hope this doesn't allocate */
  672.       if (fwrite(buf, 1, strlen(buf), stderr) != strlen(buf))
  673.           ABORT("write to stderr failed");
  674. #   else
  675.       if (write(2, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
  676. #   endif
  677. }
  678.  
  679. void GC_err_puts(s)
  680. char *s;
  681. {
  682. #   ifdef OS2
  683.       /* We hope this doesn't allocate */
  684.       if (fwrite(s, 1, strlen(s), stderr) != strlen(s))
  685.           ABORT("write to stderr failed");
  686. #   else
  687.       if (write(2, s, strlen(s)) < 0) ABORT("write to stderr failed");
  688. #   endif
  689. }
  690.  
  691.